from . import passport_blue
from flask import request, jsonify, make_response, current_app, session
from info.utils.response_code import RET
from info import redis_store, constants, db
from info.utils.captcha.captcha import captcha
import re, random
#导入云通讯扩展包的类
from info.libs.yuntongxun import sms
# 导入模型类里的用户类用来查询是否注册过账号
from info.models import User

@passport_blue.route('/image_code')
def generate_image_code():
    # 1前端通过img标签的src属性访问这个视图函数，带过来的唯一参数uuid通过request.args.get()获取
    # 2判断这个获得的参数uuid是否存在，如果不存在直接返回报错给前端浏览器，
    # 3如果存在，则调用captcha生成图片验证码：name, text, image
    # 4在服务器redis数据库中存放图片验证码，通过以：
    # 5返回图片本身image，通过响应对象make_response(image),它会把这个图片直接返回给浏览器，返回response
    #  需要指定响应数据类型为image/jpg

    image_code_id = request.args.get('image_code_id')
    print(image_code_id)
    if not image_code_id: # 如果图片的uuid不存在，返回一个json字符串
        json_str = jsonify(errno=RET.PARAMERR, errmsg='参数缺失')
        return json_str
    name, text, image = captcha.generate_captcha()
    try: #s设置数据库存入的键，过期时间，值
        redis_store.setex('ImageCode_'+image_code_id, constants.SMS_CODE_REDIS_EXPIRES, text)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据保存图片异常')
    #如果存入数据库成功，返回图片给前端
    else:
        response = make_response(image)
        response.headers['Content-Type'] = 'image/jpg'
        return response

@passport_blue.route("/sms_code", methods=['POST'])
def send_sms_code():
    """
    发送短信：获取参数、校验参数、业务处理、返回结果
    1、获取参数，post请求的json数据，mobile,image_code,image_code_id
    2、判断参数是否存在，all/or
    3、校验手机号格式是否正确，正则
    4、获取本地redis数据库中存储的真实图片验证码；只能get一次，无论用户输入正确与否，都需要删除图片验证码
    5、判断获取结果，如果不存在，直接终止程序执行，图片验证码已过期
    6、删除图片验证码
    7、比较图片验证码是否一致，因为图片验证码只能比较一次；
    8、需要判断手机号是否已注册
    9、构造短信验证码的随机数，六位数，random.randint()
    10、在redis数据库中存储短信验证码随机数
    12、调用云通讯接口发送短信，保存发送结果
    12、判断发送是否成功
    :return:
    """
    # 获取post请求的参数
    mobile = request.json.get('mobile')
    image_code = request.json.get("image_code")
    image_code_id = request.json.get("image_code_id")
    # 判断参数的完整性
    # if mobile and image_code and image_code_id:
    if not all([mobile, image_code, image_code_id]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数不完整')
    # 检查手机号的格式
    if not re.match(r'^1[3456789]\d{9}$', mobile):
        return jsonify(errno=RET.PARAMERR, errmsg='手机号格式错误')
    # 从redis数据库中获取本地的真实的图片验证码
    try:
        real_image_code = redis_store.get('ImageCode_' + image_code_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='获取图片验证码失败')
    # 判断获取结果是否存在
    if not real_image_code:
        return jsonify(errno=RET.NODATA, errmsg='图片验证码已过期')
    # 删除图片验证码，因为图片验证码只能get一次
    try:
        redis_store.delete('ImageCode_' + image_code_id)
    except Exception as e:
        current_app.logger.error(e)
    # 比较图片验证码是否一致,忽略大小写
    if real_image_code.lower() != image_code.lower():
        return jsonify(errno=RET.DATAERR, errmsg='图片验证码错误')
    # 判断手机号是否已经注册
    try:
        user = User.query.filter(User.mobile == mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询数据库异常')
    else:
        # 判断查询结果是否有数据
        if user is not None:
            return jsonify(errno=RET.DATAEXIST, errmsg='手机号已注册')

    # 生成短信随机数
    sms_code = '%06d' % random.randint(0, 999999)
    print(sms_code)
    # 保存到redis数据库中
    try:
        redis_store.setex('SMSCode_' + mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='保存短信验证码失败')
    # 调用云通讯发送短信
    try:
        ccp = sms.CCP()
        # 调用云通讯的模板方法，发送短信
        result = ccp.send_template_sms(mobile, [sms_code, constants.SMS_CODE_REDIS_EXPIRES / 60], 1)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.THIRDERR, errmsg='发送短信异常')
    # 判断发送结果
    # if result == 0:
    if 0 == result:
        return jsonify(errno=RET.OK, errmsg='发送成功')
    else:
        return jsonify(errno=RET.THIRDERR, errmsg='发送失败')

@passport_blue.route('/register', methods=['POST'])
def register():
    # 用户注册
    # 1 获得前台发送的参数：mobile, smscode, password
    # 2 三个参数的完整性
    # 3 校验手机号码的格式
    # 4 获取redis存储的短信验证码，1如果获取失败返回中断信息，2如果获取成功但是获取的内容为空，则过期
    # 5 先比较短信验证码是否正确，再删除redis中短信验证码，因为短信验证码可以比较多次，
    # 6 查询mysql数据库，确认数据库不能存在电话，确认用户没注册
    # 7 判断查询结果
    # 8 构造模型类对象，保存用户数据
    # 9 提交数据到mysql数据库
    # 10把用户信息缓存到redis数据库中

    # mobile = request.json.get('mobile')
    # sms_code = request.json.get('sms_code')
    # password = request.json.get('password')
    mobile= request.get_json('mobile')
    sms_code = request.get_json('sms_code')
    password = request.get_json('password')
    if not all([mobile, sms_code, password]):
        return jsonify(errno=RET.PARAMERR, errmsg='缺少必要信息')
    use_mobile = re.match(r'^1[3456789][0-9]{9}$', mobile)
    if not use_mobile:
        return jsonify(errno=RET.PARAMERR, errmsg='手机号码不正确')
    if use_mobile:
        try:
            real_sms_code = redis_store.get('SMSCode_' + mobile)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg='数据库异常')
    if not real_sms_code:
        return jsonify(errno=RET.NODATA, errmsg='验证码已经过期')
    if real_sms_code != str(sms_code):
        return jsonify(errno=RET.DATAERR, errmsg='验证码不正确')
    try:
        redis_store.delete('SMSCode'+mobile)
    except Exception as e:
        current_app.logger.error(e)
        #return jsonify(errno=RET.DBERR, errmsg='数据库异常')

    try:
        user = User.query.filter(User.mobile==mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询数据库异常')
    if user:
        return jsonify(errno=RET.DATAEXIST, errmsg='手机号码已经注册')
    user = User()
    user.mobile = mobile
    user.nick_name = mobile
    user.password = password
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='信息存储失败')

    session['user_id'] = user.id
    session['mobile'] = mobile
    session['nick_name'] = mobile
    return jsonify(errno=RET.OK, errmsg='注册成功')







# # 发送短信验证
# @passport_blue.route('/sms_code', methods=['POST'])
# def send_sms_code():
#     # 1获取参数post请求的json参数,mobile,image_code,image_code_id
#     # 2 如果三个参数不同时存在返回错误信息。
#     # 3 如果存在，对手机号进行正则匹配，并且获取本地redis数据库中存储的图片验证吗
#     # 只能获取get一次，
#     # 4 如果不存在redis数据库中，则终止并且返回图片验证过期
#     # 5 先删除，再比较图片
#     # 6 云通讯不提供随机码，需要自己生成随机数字
#     # 7在redis中存储短信验证码随机数
#     # 8调用云通信接口发送短信，保存发送结果
#     # 9 判断发送是否成功，失败，返回失败信息
#     mobile = request.json.get('mobile')
#     image_code = request.json.get('image_code')
#     image_code_id = request.json.get('image_code_id')
#     if not all([mobile,image_code,image_code_id]):
#         # 如果三个参数有一个不存在，则立马返回错误提示
#         # if (not mobile) or (not image_code) or (not image_code_id):
#         return jsonify(errno=RET.PARAMERR, errmsg='发送数据有误')
#     # 如果手机匹配不正确，返回错误信息
#     if not re.match(r'^1[3456789][0-9]{9}$', mobile):
#         return jsonify(errno=RET.PARAMERR, errmsg='手机号码填写错误')
#
#     # 如果从redis数据库中获取图片
#     try: #t 通过前端获取的uui查找数据库里的唯一数据
#         redis_image_code = redis_store.get('ImageCode_'+image_code_id)
#     except Exception as e: # 如果没有找到，则写入日志 返回错误信息
#         current_app.logger.error(e)
#         return jsonify(errno=RET.DBERR, errmsg='没有找到图片验证码，获取失败')
#     # 如果没有这个图片信息
#     if not redis_image_code:
#         return jsonify(errno=RET.NODATA,errmsg='图片验证码过期')
#     # 如果在redis数据库存在图片验证码，则先删除数据库里的信息再做比较
#     try:
#         redis_store.delete('ImageCode_'+image_code_id)
#     except Exception as e:
#         current_app.logger.error(e)
#     # 如果前端发过来的图片text和数据库里的通过uuid找到的text不相同返回错误信息
#     if image_code.upper() != redis_image_code.upper():
#         return jsonify(errno=RET.DATAERR, errmsg='图片验证码不正确')
#     #如果验证成功，则发送短信验证
#     #!判断手机号码是否已经注册过，查询mysql数据库
#     try:
#         User_mobile = User.query.filte(User.mobile == mobile).first()
#     except Exception as e:
#         current_app.logger.error(e)
#         return jsonify(errno=RET.DBERR, errmsg='查询数据库错误')
#     # 如果用户注册过,直接返回信息
#     else:
#         if User_mobile:
#             return jsonify(errno=RET.DATAEXIST, errmsg='该手机号码已经注册过')
#     #1 生成6位随机数
#     sms_code = ''
#     for i in range(6):
#         sms_code += str(random.randint(0, 9))
#     #2 把这个6位随机数，以手机号为键，保存到redis数据库中，并设置过期时间
#     try:
#         redis_store.setex('SMSCode'+mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
#     except Exception as e:
#         current_app.logger.error(e)
#         return jsonify(errno=RET.DBERR, errmsg='保存验证码失败')
#     #3 调用云通讯发送短信,调用第三方接口需要try
#     try:
#         ccp = CCP()
#         # 参数发送的号码，【 短信验证码，过期时间5分钟】模版
#         result = ccp.send_template_sms(mobile, [sms_code, constants.SMS_CODE_REDIS_EXPIRES/60], 1)
#     except Exception as e:
#         current_app.logger.error(e)
#         return jsonify(errno=RET.THIRDERR, errmsg='发送短信验证码失败')
#     # 判断短信发送结果：
#     if 0 == result:
#         return jsonify(errno=RET.OK, errmsg='发送成功')
#     else:
#         return jsonify(errno=RET.THIRDERR, errmsg='发送失败')
